--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit bf443b6e2d65f45973bfd3749dd4397d0d1ab50d
Parents : adc4ce2
Author : Ivan <ivan@quad4.io>
Signature : Invalid signer <e46112d44649266d71fe2193e00a4710>, author is <ivan@quad4.io>
Date : 2026-07-04T16:09:34-05:00
feat(github-actions): add new actions for fetching frontend artifacts and setting up development environments, update workflows to utilize these actions
Changes
16 files changed, 461 insertions(+), 780 deletions(-)
Diff
diff --git a/.github/actions/fetch-frontend-artifact/action.yml b/.github/actions/fetch-frontend-artifact/action.yml
new file mode 100644
index 00000000..3a1efbaa
--- /dev/null
+++ b/.github/actions/fetch-frontend-artifact/action.yml
@@ -0,0 +1,32 @@
+# Pinned actions (bump tag and SHA together when upgrading):
+# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
+name: Fetch frontend artifact
+description: Download a prebuilt meshchatx/public artifact and verify required paths
+
+inputs:
+ artifact-name:
+ description: Artifact name from the reusable frontend-build workflow
+ required: true
+ path:
+ description: Destination directory for meshchatx/public contents
+ required: false
+ default: meshchatx/public
+
+runs:
+ using: composite
+ steps:
+ - name: Download frontend artifact
+ uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ with:
+ name: ${{ inputs.artifact-name }}
+ path: ${{ inputs.path }}
+
+ - name: Verify frontend artifact contents
+ shell: bash
+ env:
+ FRONTEND_PATH: ${{ inputs.path }}
+ run: |
+ set -euo pipefail
+ test -f "${FRONTEND_PATH}/index.html"
+ test -d "${FRONTEND_PATH}/assets"
+ test -d "${FRONTEND_PATH}/reticulum-docs-bundled/current"
diff --git a/.github/actions/setup-dev-environment/action.yml b/.github/actions/setup-dev-environment/action.yml
new file mode 100644
index 00000000..7ba80554
--- /dev/null
+++ b/.github/actions/setup-dev-environment/action.yml
@@ -0,0 +1,37 @@
+name: Set up development environment
+description: Python/UV, Node/pnpm, and full project dependencies for CI jobs
+
+inputs:
+ python-version:
+ description: Python version
+ required: true
+ uv-version:
+ description: UV version installed from PyPI
+ required: false
+ default: "0.11.15"
+ node-version:
+ description: Node.js version
+ required: true
+ pnpm-version:
+ description: pnpm version activated through corepack
+ required: false
+ default: "11.1.2"
+
+runs:
+ using: composite
+ steps:
+ - name: Set up Python and UV
+ uses: ./.github/actions/setup-python-uv
+ with:
+ python-version: ${{ inputs.python-version }}
+ uv-version: ${{ inputs.uv-version }}
+
+ - name: Set up Node and pnpm
+ uses: ./.github/actions/setup-node-pnpm
+ with:
+ node-version: ${{ inputs.node-version }}
+ pnpm-version: ${{ inputs.pnpm-version }}
+
+ - name: Install dependencies
+ shell: bash
+ run: bash scripts/ci/github-install-deps.sh
diff --git a/.github/actions/setup-python-uv/action.yml b/.github/actions/setup-python-uv/action.yml
new file mode 100644
index 00000000..dbe23c93
--- /dev/null
+++ b/.github/actions/setup-python-uv/action.yml
@@ -0,0 +1,36 @@
+# Pinned actions (bump tag and SHA together when upgrading):
+# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
+# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
+name: Set up Python and UV
+description: Python runtime, pinned UV installer, and UV download cache
+
+inputs:
+ python-version:
+ description: Python version
+ required: true
+ uv-version:
+ description: UV version installed from PyPI
+ required: false
+ default: "0.11.15"
+
+runs:
+ using: composite
+ steps:
+ - name: Set up Python
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ with:
+ python-version: ${{ inputs.python-version }}
+
+ - name: Install UV (PyPI pin)
+ shell: bash
+ env:
+ UV_VERSION: ${{ inputs.uv-version }}
+ run: bash scripts/ci/github-install-uv.sh
+
+ - name: Cache UV downloads
+ uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
+ with:
+ path: ~/.cache/uv
+ key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-uv-
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index e344dc72..91094bda 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -12,3 +12,19 @@ updates:
- electron
- electron-*
- "@electron/*"
+
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ open-pull-requests-limit: 10
+ groups:
+ actions:
+ patterns:
+ - actions/*
+ - docker/*
+ - github/*
+ - sigstore/*
+ - pypa/*
+ - benchmark-action/*
+ - slsa-framework/*
diff --git a/.github/workflows/android-apk-tag.yml b/.github/workflows/android-apk-tag.yml
index b5c59f97..f64be54c 100644
--- a/.github/workflows/android-apk-tag.yml
+++ b/.github/workflows/android-apk-tag.yml
@@ -114,17 +114,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Install Android wheel build dependencies
run: |
diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml
index e73a6b31..01b37c3f 100644
--- a/.github/workflows/android-build.yml
+++ b/.github/workflows/android-build.yml
@@ -35,7 +35,7 @@ permissions:
actions: write
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: android-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
@@ -142,17 +142,9 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Install Android wheel build dependencies
run: |
diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml
index f4707da2..92f9adb4 100644
--- a/.github/workflows/bench.yml
+++ b/.github/workflows/bench.yml
@@ -5,8 +5,6 @@
#
# Pinned first-party actions (bump tag and SHA together when upgrading):
# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
-# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
# benchmark-action/github-action-benchmark@v1.22.0
# a60cea5bc7b49e15c1f58f411161f99e0df48372
@@ -21,7 +19,7 @@ on:
- dev
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: bench-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
@@ -43,33 +41,14 @@ jobs:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
+ uv-version: ${{ env.UV_VERSION }}
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- name: Setup Task
run: sh scripts/ci/setup-task.sh
@@ -100,10 +79,6 @@ jobs:
output-file-path: bench_results.json
external-data-json-path: ./cache/benchmark-data.json
github-token: ${{ secrets.GITHUB_TOKEN }}
- # GitHub shared runners have 20-40% variance even with identical
- # code. alert-threshold posts a comment; fail-threshold fails
- # the job. Sub-ms operations are especially noisy so we keep
- # the comment bar at 2x and the hard-fail bar at 3x.
alert-threshold: "200%"
fail-threshold: "300%"
fail-on-alert: true
diff --git a/.github/workflows/build-linux-packages.yml b/.github/workflows/build-linux-packages.yml
index 695c5eca..2a5ed97d 100644
--- a/.github/workflows/build-linux-packages.yml
+++ b/.github/workflows/build-linux-packages.yml
@@ -1,13 +1,9 @@
# Linux packaging build test: AppImage, deb, rpm, Flatpak (branches and PRs).
-# Tagged release assets run in .github/workflows/build-release.yml with draft.
+# Tagged release assets run in build-release.yml with draft.
#
# Pinned first-party actions (bump tag and SHA together when upgrading):
# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
-# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
# actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4
-# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
-# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
name: Build Linux packages
@@ -25,13 +21,14 @@ on:
- ".github/workflows/build-linux-packages.yml"
- ".github/workflows/build-release.yml"
- ".github/workflows/frontend-build.yml"
+ - ".github/actions/**"
workflow_dispatch:
permissions:
contents: read
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: linux-packages-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
@@ -52,10 +49,18 @@ jobs:
artifact_name: meshchatx-frontend-linux-pkg-${{ github.run_id }}-${{ github.run_attempt }}
retention_days: 1
- linux-test-x64:
- name: Linux build test (x64)
+ linux-test:
+ name: Linux build test (${{ matrix.arch }})
needs: frontend
- runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - arch: x64
+ runner: ubuntu-latest
+ - arch: arm64
+ runner: ubuntu-24.04-arm
+ runs-on: ${{ matrix.runner }}
timeout-minutes: 120
permissions:
contents: read
@@ -67,23 +72,11 @@ jobs:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up Python and UV
+ uses: ./.github/actions/setup-python-uv
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
+ uv-version: ${{ env.UV_VERSION }}
- name: Set up Node and pnpm
uses: ./.github/actions/setup-node-pnpm
@@ -94,93 +87,13 @@ jobs:
- name: Linux packaging APT dependencies
run: bash scripts/ci/github-apt-linux-packaging.sh
- - name: Install project dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
- with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
-
- - name: Setup Task
- run: sh scripts/ci/setup-task.sh
-
- - name: Build release-assets
- run: bash scripts/ci/github-build-linux-release-assets.sh
-
- - name: Upload Linux build-test artifact (x64)
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
- with:
- name: meshchatx-linux-build-test-x64-${{ github.ref_name }}-${{ github.run_id }}
- path: release-assets/
- if-no-files-found: warn
- retention-days: 1
-
- linux-test-arm64:
- name: Linux build test (arm64)
- needs: frontend
- runs-on: ubuntu-24.04-arm
- timeout-minutes: 120
- permissions:
- contents: read
- actions: write
- env:
- FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }}
- MESHCHATX_FRONTEND_PREBUILT: "1"
- steps:
- - name: Checkout
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
-
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
- with:
- python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
- node-version: ${{ env.NODE_VERSION }}
- pnpm-version: ${{ env.PNPM_VERSION }}
-
- - name: Linux packaging APT dependencies
- run: bash scripts/ci/github-apt-linux-packaging.sh
-
- - name: Install project dependencies
+ - name: Install dependencies
run: bash scripts/ci/github-install-deps.sh
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Setup Task
run: sh scripts/ci/setup-task.sh
@@ -188,10 +101,10 @@ jobs:
- name: Build release-assets
run: bash scripts/ci/github-build-linux-release-assets.sh
- - name: Upload Linux build-test artifact (arm64)
+ - name: Upload Linux build-test artifact (${{ matrix.arch }})
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with:
- name: meshchatx-linux-build-test-arm64-${{ github.ref_name }}-${{ github.run_id }}
+ name: meshchatx-linux-build-test-${{ matrix.arch }}-${{ github.ref_name }}-${{ github.run_id }}
path: release-assets/
if-no-files-found: warn
retention-days: 1
@@ -231,45 +144,18 @@ jobs:
org.freedesktop.Sdk//25.08 \
org.electronjs.Electron2.BaseApp//25.08
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
+ uv-version: ${{ env.UV_VERSION }}
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Build flatpak bundle
run: bash scripts/ci/github-build-linux-flatpak.sh
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
index 340226a6..1f0abb96 100644
--- a/.github/workflows/build-release.yml
+++ b/.github/workflows/build-release.yml
@@ -15,8 +15,9 @@
# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
# actions/setup-java@v4.7.1 c5195efecf7bdfc987ee8bae7a71cb8b11521c00
#
-# SLSA generator (must stay @vX.Y.Z semver per upstream):
+# SLSA generator (pinned to v2.1.0 commit):
# slsa-framework/slsa-github-generator/generator_generic_slsa3.yml@v2.1.0
+# f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
name: Build release
@@ -81,9 +82,19 @@ jobs:
run_unit_tests: true
linux-release:
- name: Linux release assets (x64)
+ name: Linux release assets (${{ matrix.arch }})
needs: frontend
- runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - arch: x64
+ runner: ubuntu-latest
+ setup_trivy: true
+ - arch: arm64
+ runner: ubuntu-24.04-arm
+ setup_trivy: false
+ runs-on: ${{ matrix.runner }}
timeout-minutes: 120
permissions:
contents: read
@@ -95,23 +106,11 @@ jobs:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up Python and UV
+ uses: ./.github/actions/setup-python-uv
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
+ uv-version: ${{ env.UV_VERSION }}
- name: Set up Node and pnpm
uses: ./.github/actions/setup-node-pnpm
@@ -122,114 +121,40 @@ jobs:
- name: Linux packaging APT dependencies
run: bash scripts/ci/github-apt-linux-packaging.sh
- - name: Install project dependencies
+ - name: Install dependencies
run: bash scripts/ci/github-install-deps.sh
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Setup Task
+ if: matrix.setup_trivy
run: sh scripts/ci/setup-task.sh
- name: Apt update (for Trivy .deb)
+ if: matrix.setup_trivy
run: sh scripts/ci/exec-priv.sh apt-get update -qq
- name: Setup Trivy
+ if: matrix.setup_trivy
run: sh scripts/ci/setup-trivy.sh
- name: Build release-assets
run: bash scripts/ci/github-build-linux-release-assets.sh
- - name: Upload Linux release artifact (x64)
+ - name: Upload Linux release artifact (${{ matrix.arch }})
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with:
- name: meshchatx-linux-release-x64-${{ github.ref_name }}-${{ github.run_id }}
- path: release-assets/
- if-no-files-found: error
- retention-days: 30
-
- linux-release-arm64:
- name: Linux release assets (arm64)
- needs: frontend
- runs-on: ubuntu-24.04-arm
- timeout-minutes: 120
- permissions:
- contents: read
- actions: write
- env:
- FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }}
- MESHCHATX_FRONTEND_PREBUILT: "1"
- steps:
- - name: Checkout
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
-
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
- with:
- python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
- node-version: ${{ env.NODE_VERSION }}
- pnpm-version: ${{ env.PNPM_VERSION }}
-
- - name: Linux packaging APT dependencies
- run: bash scripts/ci/github-apt-linux-packaging.sh
-
- - name: Install project dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
- with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
-
- - name: Build release-assets
- run: bash scripts/ci/github-build-linux-release-assets.sh
-
- - name: Upload Linux release artifact (arm64)
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
- with:
- name: meshchatx-linux-release-arm64-${{ github.ref_name }}-${{ github.run_id }}
+ name: meshchatx-linux-release-${{ matrix.arch }}-${{ github.ref_name }}-${{ github.run_id }}
path: release-assets/
if-no-files-found: error
retention-days: 30
collect-linux-slsa-subjects:
name: SLSA subjects + cosign (Linux)
- needs: [linux-release, linux-release-arm64]
+ needs: [linux-release]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
outputs:
@@ -542,7 +467,7 @@ jobs:
id-token: write
contents: write
actions: read
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
with:
base64-subjects: ${{ needs.collect-linux-slsa-subjects.outputs.hashes }}
upload-assets: false
@@ -560,7 +485,7 @@ jobs:
id-token: write
contents: write
actions: read
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
with:
base64-subjects: ${{ needs.collect-desktop-slsa-subjects.outputs.hashes }}
upload-assets: false
@@ -609,7 +534,7 @@ jobs:
id-token: write
contents: write
actions: read
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
with:
base64-subjects: ${{ needs.collect-android-flatpak-slsa-subjects.outputs.hashes }}
upload-assets: false
@@ -619,7 +544,6 @@ jobs:
name: Draft GitHub release (all assets + SLSA)
needs:
- linux-release
- - linux-release-arm64
- collect-linux-slsa-subjects
- slsa-provenance-linux
- build-release
@@ -633,7 +557,6 @@ jobs:
!cancelled() &&
startsWith(github.ref, 'refs/tags/') &&
needs.linux-release.result == 'success' &&
- needs.linux-release-arm64.result == 'success' &&
needs.collect-linux-slsa-subjects.result == 'success' &&
needs.slsa-provenance-linux.result == 'success' &&
(needs.build-release.result == 'success' || needs.build-release.result == 'failure') &&
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 854597ae..00000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,144 +0,0 @@
-# Native build verification (Windows + macOS).
-#
-# Pulls the prebuilt meshchatx/public artifact produced by the reusable
-# Frontend build workflow so that each platform job only has to compile the
-# cx_Freeze backend and run electron-builder.
-#
-# Pinned first-party actions (bump tag and SHA together when upgrading):
-# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
-# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
-# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
-
-name: Build
-
-on:
- push:
- branches:
- - dev
- pull_request:
- branches:
- - dev
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- NODE_OPTIONS: --max-old-space-size=8192
- PYTHON_VERSION: "3.14"
- NODE_VERSION: "24"
- UV_VERSION: "0.11.15"
- PNPM_VERSION: "11.1.2"
-
-jobs:
- frontend:
- name: Build frontend artifact
- uses: ./.github/workflows/frontend-build.yml
- permissions:
- contents: read
- with:
- artifact_name: meshchatx-frontend-build-${{ github.run_id }}-${{ github.run_attempt }}
- retention_days: 1
-
- build-test:
- name: Build test (${{ matrix.label }})
- needs: frontend
- permissions:
- contents: read
- strategy:
- fail-fast: false
- matrix:
- include:
- - os: windows-latest
- label: windows
- timeout: 120
- build_script: scripts/ci/github-build-windows.sh
- - os: macos-latest
- label: macos
- timeout: 180
- build_script: scripts/ci/github-build-macos.sh
- runs-on: ${{ matrix.os }}
- timeout-minutes: ${{ matrix.timeout }}
- defaults:
- run:
- shell: bash
- env:
- FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }}
- MESHCHATX_FRONTEND_PREBUILT: "1"
- steps:
- - name: Checkout
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
-
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
- with:
- python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
- node-version: ${{ env.NODE_VERSION }}
- pnpm-version: ${{ env.PNPM_VERSION }}
-
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Install Rosetta (Apple Silicon)
- if: matrix.label == 'macos'
- run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license || true
-
- - name: Ensure x86_64 Homebrew (/usr/local) for universal slice
- if: matrix.label == 'macos'
- run: bash scripts/ci/github-ensure-macos-x86-64-homebrew.sh
-
- - name: Set up Python x64 for cx_Freeze universal slice
- id: python_x64
- if: matrix.label == 'macos'
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
- with:
- python-version: ${{ env.PYTHON_VERSION }}
- architecture: x64
- update-environment: false
-
- - name: Install x86_64 codec2 for pycodec2 (universal slice)
- if: matrix.label == 'macos'
- run: |
- set -euo pipefail
- arch -x86_64 /usr/local/bin/brew install codec2
-
- - name: Install Rust x86_64-apple-darwin target (cbor2 x64 slice)
- if: matrix.label == 'macos'
- run: bash scripts/ci/github-macos-rust-x64-target.sh
-
- - name: Install project deps into x64 Python (mac universal cx_Freeze)
- if: matrix.label == 'macos'
- env:
- PY_X64: ${{ steps.python_x64.outputs.python-path }}
- run: bash scripts/ci/github-install-macos-x64-python-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
- with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
-
- - name: Build distributables
- run: bash "${{ matrix.build_script }}"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fbc53b42..2dec3718 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,16 +1,14 @@
-# Linux CI: lint, frontend/backend tests, localization, and a Linux build check.
+# Primary CI: lint, tests, localization, Linux build check, E2E, and native builds (dev).
#
-# The frontend bundle is produced once by the reusable Frontend build workflow
-# and downloaded by the Linux build-check job (and by the platform build/release
-# workflows) instead of being rebuilt on every job.
+# The frontend bundle is built once via the reusable frontend-build workflow and
+# downloaded by downstream jobs instead of rebuilding on every runner.
#
# Pinned first-party actions (bump tag and SHA together when upgrading):
# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
# actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4
# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
-# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
+
name: CI
on:
@@ -27,7 +25,7 @@ permissions:
contents: read
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
@@ -75,33 +73,14 @@ jobs:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
+ uv-version: ${{ env.UV_VERSION }}
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- name: Run matrix task
run: |
set -euo pipefail
@@ -143,45 +122,18 @@ jobs:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
+ uv-version: ${{ env.UV_VERSION }}
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Compile backend sources
run: uv run python -m compileall meshchatx/
@@ -222,33 +174,43 @@ jobs:
test -n "$(ls -A .artifacts/linux-build-check/build/exe)"
echo "Linux build artifact download + content validation passed."
- e2e:
- name: E2E smoke
- runs-on: ubuntu-latest
- timeout-minutes: 20
+ native-build:
+ name: Native build (${{ matrix.label }})
+ if: >-
+ github.ref == 'refs/heads/dev' ||
+ (github.event_name == 'pull_request' && github.base_ref == 'dev')
+ needs: frontend
permissions:
contents: read
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: windows-latest
+ label: windows
+ timeout: 120
+ build_script: scripts/ci/github-build-windows.sh
+ - os: macos-latest
+ label: macos
+ timeout: 180
+ build_script: scripts/ci/github-build-macos.sh
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: ${{ matrix.timeout }}
+ defaults:
+ run:
+ shell: bash
+ env:
+ FRONTEND_ARTIFACT_NAME: ${{ needs.frontend.outputs.artifact_name }}
+ MESHCHATX_FRONTEND_PREBUILT: "1"
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up Python and UV
+ uses: ./.github/actions/setup-python-uv
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
+ uv-version: ${{ env.UV_VERSION }}
- name: Set up Node and pnpm
uses: ./.github/actions/setup-node-pnpm
@@ -259,5 +221,64 @@ jobs:
- name: Install dependencies
run: bash scripts/ci/github-install-deps.sh
+ - name: Install Rosetta (Apple Silicon)
+ if: matrix.label == 'macos'
+ run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license || true
+
+ - name: Ensure x86_64 Homebrew (/usr/local) for universal slice
+ if: matrix.label == 'macos'
+ run: bash scripts/ci/github-ensure-macos-x86-64-homebrew.sh
+
+ - name: Set up Python x64 for cx_Freeze universal slice
+ id: python_x64
+ if: matrix.label == 'macos'
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+ architecture: x64
+ update-environment: false
+
+ - name: Install x86_64 codec2 for pycodec2 (universal slice)
+ if: matrix.label == 'macos'
+ run: |
+ set -euo pipefail
+ arch -x86_64 /usr/local/bin/brew install codec2
+
+ - name: Install Rust x86_64-apple-darwin target (cbor2 x64 slice)
+ if: matrix.label == 'macos'
+ run: bash scripts/ci/github-macos-rust-x64-target.sh
+
+ - name: Install project deps into x64 Python (mac universal cx_Freeze)
+ if: matrix.label == 'macos'
+ env:
+ PY_X64: ${{ steps.python_x64.outputs.python-path }}
+ run: bash scripts/ci/github-install-macos-x64-python-deps.sh
+
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
+ with:
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
+
+ - name: Build distributables
+ run: bash "${{ matrix.build_script }}"
+
+ e2e:
+ name: E2E smoke
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+ uv-version: ${{ env.UV_VERSION }}
+ node-version: ${{ env.NODE_VERSION }}
+ pnpm-version: ${{ env.PNPM_VERSION }}
+
- name: Run Playwright smoke E2E
run: bash scripts/ci/github-e2e.sh
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index b064471f..c61f5c23 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -44,7 +44,7 @@ permissions:
id-token: write
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: docker-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml
index 5cfb925c..5e5a18b4 100644
--- a/.github/workflows/pypi.yml
+++ b/.github/workflows/pypi.yml
@@ -16,8 +16,9 @@
# actions/upload-artifact@v5.0.0 330a01c490aca151604b8cf639adc76d48f6c5d4
# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
#
-# SLSA generator (must stay @vX.Y.Z semver per upstream):
+# SLSA generator (pinned to v2.1.0 commit):
# slsa-framework/slsa-github-generator/generator_generic_slsa3.yml@v2.1.0
+# f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
#
# Third-party pin (resolve before bumping release/v1):
# curl -sS "https://api.github.com/repos/pypa/gh-action-pypi-publish/commits/release/v1" | jq -r '.sha'
@@ -80,18 +81,10 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend bundle in tree
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Install build
run: python -m pip install -U pip "build>=1.2.0"
@@ -173,7 +166,7 @@ jobs:
id-token: write
contents: write
actions: read
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
+ uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@f7dd8c54c2067bafc12ca7a55595d5ee9b75204a
with:
base64-subjects: ${{ needs.build.outputs.hashes }}
upload-assets: false
diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml
deleted file mode 100644
index bcfc2d94..00000000
--- a/.github/workflows/security-scan.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-# Security scans migrated from .gitea/workflows/scan.yml.
-#
-# Pinned first-party actions (bump tag and SHA together when upgrading):
-# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
-# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
-# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
-
-# FIXME: CVE-2026-3219 affects pip through 26.0.1 waiting for next release to fix for now we ignore it
-
-name: Security scans
-
-on:
- schedule:
- - cron: "30 12 * * 1"
- push:
- branches:
- - master
- - dev
- workflow_dispatch:
-
-permissions:
- contents: read
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- PYTHON_VERSION: "3.14"
- NODE_VERSION: "24"
- UV_VERSION: "0.11.15"
- PNPM_VERSION: "11.1.2"
- COSIGN_VERSION: "3.0.6"
- # Official .deb; setup-trivy.sh verifies sigstore + SHA256 (see build-release.yml).
- TRIVY_VERSION: "0.69.3"
-
-jobs:
- scan:
- runs-on: ubuntu-latest
- timeout-minutes: 45
- permissions:
- contents: read
- steps:
- - name: Checkout
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
-
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
- with:
- python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
- node-version: ${{ env.NODE_VERSION }}
- pnpm-version: ${{ env.PNPM_VERSION }}
-
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: pip-audit
- run: |
- uv run pip install --upgrade "pip>=26.0" pip-audit
- uv run pip-audit --ignore-vuln CVE-2026-3219
-
- - name: Apt update (for Trivy .deb)
- run: sh scripts/ci/exec-priv.sh apt-get update -qq
-
- - name: Setup Trivy
- run: sh scripts/ci/setup-trivy.sh
-
- - name: Trivy filesystem scan (dependencies)
- run: sh scripts/ci/trivy-fs-scan.sh
-
- - name: Trivy Dockerfile misconfiguration
- run: trivy config --exit-code 1 Dockerfile
diff --git a/.github/workflows/codeql.yml b/.github/workflows/security.yml
similarity index 62%
rename from .github/workflows/codeql.yml
rename to .github/workflows/security.yml
index d6418c89..4e0bdf2d 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/security.yml
@@ -1,20 +1,26 @@
+# Dependency audits, filesystem/container config scans, and CodeQL analysis.
+#
# Pinned first-party actions (bump tag and SHA together when upgrading):
# actions/checkout@v6.0.1 8e8c483db84b4bee98b60c0593521ed34d9990e8
-# actions/setup-python@v6.2.0 a309ff8b426b58ec0e2a45f0f869d46889d02405
-# actions/setup-node@v6.1.0 395ad3262231945c25e8478fd5baf05154b1d79f
# actions/download-artifact@v5.0.0 634f93cb2916e3fdff6788551b99b062d0335ce0
# github/codeql-action/init@v4.31.6 95e58e9a2cdfd71adc6e0353d5c52f41a045d225
# github/codeql-action/analyze@v4.31.6 95e58e9a2cdfd71adc6e0353d5c52f41a045d225
-# actions/cache@v4.2.0 1bd1e32a3bdc45362d1e726936510720a7c30a57
+#
+# FIXME: CVE-2026-3219 affects pip through 26.0.1; ignored until next pip release.
-name: "CodeQL Advanced"
+name: Security
on:
push:
- branches: ["master", "dev"]
+ branches:
+ - master
+ - dev
pull_request:
- branches: ["master", "dev"]
+ branches:
+ - master
+ - dev
schedule:
+ - cron: "30 12 * * 1"
- cron: "35 18 * * 3"
workflow_dispatch:
@@ -22,7 +28,7 @@ permissions:
contents: read
concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
+ group: security-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
@@ -32,8 +38,44 @@ env:
NODE_VERSION: "24"
UV_VERSION: "0.11.15"
PNPM_VERSION: "11.1.2"
+ TRIVY_VERSION: "0.69.3"
jobs:
+ dependency-audit:
+ name: Dependency and config scan
+ runs-on: ubuntu-latest
+ timeout-minutes: 45
+ permissions:
+ contents: read
+ steps:
+ - name: Checkout
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+ uv-version: ${{ env.UV_VERSION }}
+ node-version: ${{ env.NODE_VERSION }}
+ pnpm-version: ${{ env.PNPM_VERSION }}
+
+ - name: pip-audit
+ run: |
+ uv run pip install --upgrade "pip>=26.0" pip-audit
+ uv run pip-audit --ignore-vuln CVE-2026-3219
+
+ - name: Apt update (for Trivy .deb)
+ run: sh scripts/ci/exec-priv.sh apt-get update -qq
+
+ - name: Setup Trivy
+ run: sh scripts/ci/setup-trivy.sh
+
+ - name: Trivy filesystem scan (dependencies)
+ run: sh scripts/ci/trivy-fs-scan.sh
+
+ - name: Trivy Dockerfile misconfiguration
+ run: trivy config --exit-code 1 Dockerfile
+
frontend:
name: Build frontend artifact (CodeQL)
uses: ./.github/workflows/frontend-build.yml
@@ -43,16 +85,15 @@ jobs:
artifact_name: meshchatx-frontend-codeql-${{ github.run_id }}-${{ github.run_attempt }}
retention_days: 1
- analyze:
- name: Analyze (${{ matrix.language }})
- runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ codeql:
+ name: CodeQL (${{ matrix.language }})
+ runs-on: ubuntu-latest
timeout-minutes: 360
permissions:
security-events: write
packages: read
actions: read
contents: read
-
strategy:
fail-fast: false
matrix:
@@ -65,7 +106,6 @@ jobs:
build-mode: none
- language: python
build-mode: none
-
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
@@ -81,8 +121,8 @@ jobs:
with:
category: "/language:${{matrix.language}}"
- analyze-javascript:
- name: Analyze (javascript-typescript)
+ codeql-javascript:
+ name: CodeQL (javascript-typescript)
runs-on: ubuntu-latest
needs: [frontend]
timeout-minutes: 360
@@ -98,45 +138,18 @@ jobs:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
- - name: Set up Python
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
+ - name: Set up development environment
+ uses: ./.github/actions/setup-dev-environment
with:
python-version: ${{ env.PYTHON_VERSION }}
-
- - name: Install UV (PyPI pin)
- env:
- UV_VERSION: ${{ env.UV_VERSION }}
- run: bash scripts/ci/github-install-uv.sh
-
- - name: Cache UV downloads
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57
- with:
- path: ~/.cache/uv
- key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
- restore-keys: |
- ${{ runner.os }}-uv-
-
- - name: Set up Node and pnpm
- uses: ./.github/actions/setup-node-pnpm
- with:
+ uv-version: ${{ env.UV_VERSION }}
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
- - name: Install dependencies
- run: bash scripts/ci/github-install-deps.sh
-
- - name: Download frontend artifact
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
+ - name: Fetch frontend artifact
+ uses: ./.github/actions/fetch-frontend-artifact
with:
- name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- path: meshchatx/public
-
- - name: Verify frontend artifact contents
- run: |
- set -euo pipefail
- test -f meshchatx/public/index.html
- test -d meshchatx/public/assets
- test -d meshchatx/public/reticulum-docs-bundled/current
+ artifact-name: ${{ env.FRONTEND_ARTIFACT_NAME }}
- name: Initialize CodeQL
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────